package goods_serv

import (
	"strconv"
	"strings"
	"ubt-aio-service/app/mod/goods_mod"
	"ubt-aio-service/app/pkg/db"
	"ubt-aio-service/app/utils"
)

type goodsType struct{}

var TypeServ = goodsType{}

// Add 新增
func (s *goodsType) Add(req *goods_mod.TypeSaveReq) *utils.ResJson {
	// 去掉主键，改为自动赋值模式
	sqlStr := "INSERT INTO goods_type(type_id, type_name, type_code, quanpin, jianpin, kind, parent_id, sort, logo_id, logo_name, logo_url, brand_ids, remarks, states, add_time, upd_time) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, 1, EXTRACT(epoch FROM NOW()), EXTRACT(epoch FROM NOW()))"
	return db.CudData(sqlStr, req.TypeId, req.TypeName, req.TypeCode, req.Quanpin, req.Jianpin, req.Kind, req.ParentId, req.Sort, req.LogoId, req.LogoName, req.LogoUrl, req.BrandIds, req.Remarks)
}

// Exists 判断是否重复
func (s *goodsType) Exists(req *goods_mod.TypeExtVo) bool {
	// 注意修改对应的变量值
	sqlStr := "SELECT type_id FROM goods_type WHERE states=1 AND kind=$1 AND parent_id=$2 AND (type_name=$3 OR type_code=$4)"
	param := make([]any, 0)
	param = append(param, req.Kind)
	param = append(param, req.ParentId)
	param = append(param, req.TypeName)
	param = append(param, req.TypeCode)
	if req.TypeId != "" {
		sqlStr += " AND type_id!=$5"
		param = append(param, req.TypeId)
	}
	if res := db.GetOne(sqlStr, param...); res.Code == utils.Succeed.Code {
		return true
	}
	return false
}

// Update 修改
func (s *goodsType) Update(req *goods_mod.TypeSaveReq) *utils.ResJson {
	// 注意最后的索引值修改，以及去掉不需要修改的值
	sqlStr := "UPDATE goods_type SET type_name=$1, type_code=$2, quanpin=$3, jianpin=$4, kind=$5, parent_id=$6, sort=$7, logo_id=$8, logo_name=$9, logo_url=$10, brand_ids=$11, remarks=$12, upd_time=EXTRACT(epoch FROM NOW()) WHERE type_id=$13"
	// 需要将第一个值放到最后
	return db.CudData(sqlStr, req.TypeName, req.TypeCode, req.Quanpin, req.Jianpin, req.Kind, req.ParentId, req.Sort, req.LogoId, req.LogoName, req.LogoUrl, req.BrandIds, req.Remarks, req.TypeId)
}

// Process 处理
func (s *goodsType) Process(req *goods_mod.TypeProcReq) *utils.ResJson {
	var (
		// param 数据库表操作的参数数组
		param []any
		// idList 编号数组
		idList []string
		// q 拼接SQL的点位符字符串，如$1, $2……
		q string
		// 索引序号
		n = 2
	)
	param = append(param, req.States)
	param = append(param, req.Kind)
	// 将字符串转换成数组
	idArr := strings.Split(req.Ids, ",")
	// 获取所有的分类编号
	res := db.GetAll("SELECT type_id, parent_id FROM goods_type WHERE states!=2 ORDER BY type_code")
	// 递归遍历每个分类下的子分类及子孙分类，最后返回给idList编号数组
	for _, curId := range idArr {
		idList = append(idList, curId)
		if res.Code == utils.Succeed.Code {
			idList = s.getIds(res.Data.([]map[string]any), curId, idList)
		}
	}
	// 拼接SQL
	for _, curId := range idList {
		n++
		q += "$" + strconv.Itoa(n) + ","
		param = append(param, curId)
	}
	q = q[:len(q)-1]
	sqlStr := "UPDATE goods_type SET states=$1, upd_time=EXTRACT(epoch FROM NOW()) WHERE kind=$2 AND type_id IN (" + q + ")"
	return db.CudData(sqlStr, param...)
}

// getIds 递归遍历获取子级分类编号
func (s *goodsType) getIds(list []map[string]any, id any, newList []string) []string {
	for _, item := range list {
		if id == item["parentId"] {
			newList = append(newList, item["typeId"].(string))
			newList = s.getIds(list, item["typeId"], newList)
		}
	}
	return newList
}

// One 获取详情
func (s *goodsType) One(typeId string) *utils.ResJson {
	sqlStr := "SELECT a.type_id, a.type_name, a.type_code, a.quanpin, a.jianpin, a.kind, a.parent_id, a.sort, a.logo_id, a.logo_name, a.logo_url, a.brand_ids, a.remarks, a.states, a.add_time, a.upd_time, " +
		"(CASE WHEN a.parent_id='111111111111111111111' THEN '一级分类' ELSE b.type_name END) AS parent_name, " +
		"(CASE WHEN a.parent_id='111111111111111111111' THEN '10000000' ELSE b.type_code END) AS parent_code " +
		"FROM goods_type a " +
		"LEFT JOIN goods_type b ON b.states=1 AND a.parent_id=b.type_id " +
		"WHERE a.type_id=$1"
	return db.GetOne(sqlStr, typeId)
}

// List 获取分类树状列表
func (s *goodsType) List(kind uint8) *utils.ResJson {
	sqlStr := "SELECT a.type_id, a.type_name, a.type_code, a.parent_id, a.sort, a.logo_id, a.logo_name, a.logo_url, a.states, a.add_time, " +
		"(CASE WHEN a.parent_id='111111111111111111111' THEN '一级分类' ELSE b.type_name END) AS parent_name, " +
		"(CASE WHEN a.parent_id='111111111111111111111' THEN '10000000' ELSE b.type_code END) AS parent_code " +
		"FROM goods_type a " +
		"LEFT JOIN goods_type b ON b.states=1 AND a.parent_id=b.type_id " +
		"WHERE a.states!=2 AND a.kind=$1 ORDER BY a.sort"
	res := db.GetAll(sqlStr, kind)
	if res.Code == utils.Succeed.Code {
		var newList []map[string]any
		var level uint8 = 1
		for _, item := range res.Data.([]map[string]any) {
			if item["parentId"] == "111111111111111111111" {
				item["level"] = level
				newList = append(newList, item)
				newList = s.sortChildMenu(res.Data.([]map[string]any), item["typeId"], newList, level)
			}
		}
		return &utils.ResJson{Code: utils.Succeed.Code, Msg: utils.Succeed.Msg, Data: newList}
	}
	return utils.NoData
}

// sortChildMenu 将分类按树状排序
func (s *goodsType) sortChildMenu(list []map[string]any, id any, newList []map[string]any, level uint8) []map[string]any {
	level++
	for _, item := range list {
		if id == item["parentId"] {
			item["level"] = level
			newList = append(newList, item)
			newList = s.sortChildMenu(list, item["typeId"], newList, level)
		}
	}
	return newList
}

// Tree 获取分类树状列表
func (s *goodsType) Tree(kind uint8) *utils.ResJson {
	res := db.GetAll("SELECT type_id sel_id, type_name sel_name, type_code sel_code, parent_id FROM goods_type WHERE states=1 AND kind=$1 ORDER BY type_code", kind)
	if res.Code == utils.Succeed.Code {
		var level uint8 = 0
		tree := s.buildTree("111111111111111111111", res.Data.([]map[string]any), level)
		return &utils.ResJson{Code: utils.Succeed.Code, Msg: utils.Succeed.Msg, Data: tree}
	}
	return utils.NoData
}

func (s *goodsType) buildTree(parentId any, list []map[string]any, level uint8) []map[string]any {
	tree := make([]map[string]any, 0)
	level++
	for _, child := range list {
		if parentId == child["parentId"] {
			children := s.buildTree(child["selId"], list, level)
			child["level"] = level
			child["children"] = children
			tree = append(tree, child)
		}
	}
	return tree
}

// Sort 获取分类数量，用于排序
func (s *goodsType) Sort(kind uint8, parentId string) *utils.ResJson {
	sqlStr := "SELECT COUNT(1)+1 AS nums FROM goods_type WHERE states=1 AND kind=$1 AND parent_id=$2"
	res := db.GetOne(sqlStr, kind, parentId)
	return &utils.ResJson{Code: utils.Succeed.Code, Msg: utils.Succeed.Msg, Data: res.Data.(map[string]any)["nums"].(int64)}
}

// Select 获取当前级别分类选择列表
func (s *goodsType) Select(kind uint8, parentId string) *utils.ResJson {
	sqlStr := "SELECT a.type_id sel_id, a.type_name sel_name, a.type_code sel_code, a.parent_id FROM goods_type a " +
		"WHERE a.states=1 AND a.kind=$1 AND parent_id=$2 ORDER BY a.sort"
	return db.GetAll(sqlStr, kind, parentId)
}
